from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse, HttpResponse
from django.views.decorators.http import require_http_methods
from django.contrib import messages
from django.core.paginator import Paginator
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from django.views import View
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser, FormParser
import json
import os
from django.conf import settings
from django.db.models import Count, Avg
from django.utils import timezone
from datetime import timedelta
import logging
from django.db import transaction
from django.core.serializers.json import DjangoJSONEncoder
import uuid

# 使用core的Template模型
from apps.core.models import Template, FieldConfig, ProcessingRule, DataSourceConfig, OutputConfig, ProcessingTask, UploadedFile
# 使用本地的日志模型
from .models import TemplateUsageLog
from apps.core.serializers import TemplateSerializer
from apps.core.excel_processor import ExcelProcessor
import pandas as pd


# Template management views

def template_management_index(request):
    """模板管理首页"""
    templates = Template.objects.filter(is_active=True).order_by('-created_at')
    return render(request, 'template_management/template_index.html', {
        'templates': templates
    })


def template_list(request):
    """模板列表页面"""
    # 获取搜索和过滤参数
    search = request.GET.get('search', '')
    status_filter = request.GET.get('status', '')
    sort_by = request.GET.get('sort', '-created_at')
    
    # 构建查询
    templates = Template.objects.all()
    
    if search:
        templates = templates.filter(
            name__icontains=search
        ) | templates.filter(
            description__icontains=search
        )
    
    if status_filter == 'active':
        templates = templates.filter(is_active=True)
    elif status_filter == 'inactive':
        templates = templates.filter(is_active=False)
    
    # 排序
    templates = templates.order_by(sort_by)
    
    # 分页
    paginator = Paginator(templates, 12)  # 每页12个模板
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    return render(request, 'template_management/template_list.html', {
        'templates': page_obj,
        'page_obj': page_obj,
        'is_paginated': page_obj.has_other_pages(),
    })


def template_create(request):
    """创建模板"""
    if request.method == 'GET':
        return render(request, 'template_management/template_create.html')
    
    elif request.method == 'POST':
        try:
            # 获取基本信息
            name = request.POST.get('name')
            description = request.POST.get('description', '')
            output_format = request.POST.get('output_format', 'excel')
            
            # 获取字段配置和处理逻辑
            field_configs = json.loads(request.POST.get('field_configs', '{}'))
            processing_logic_raw = request.POST.get('processing_logic', '{}')
            try:
                processing_logic = json.loads(processing_logic_raw) if isinstance(processing_logic_raw, str) else (processing_logic_raw or {})
            except json.JSONDecodeError:
                processing_logic = {}
            
            # 解析复合配置（支持 form-data 和 application/json）
            data_sources = []
            processing_rules = []
            output_configs = []
            try:
                data_sources_raw = request.POST.get('data_sources', '[]')
                processing_rules_raw = request.POST.get('processing_rules', '[]')
                output_configs_raw = request.POST.get('output_configs', '[]')
                data_sources = json.loads(data_sources_raw) if isinstance(data_sources_raw, str) else (data_sources_raw or [])
                processing_rules = json.loads(processing_rules_raw) if isinstance(processing_rules_raw, str) else (processing_rules_raw or [])
                output_configs = json.loads(output_configs_raw) if isinstance(output_configs_raw, str) else (output_configs_raw or [])
            except Exception:
                # 忽略解析错误，使用空列表
                data_sources, processing_rules, output_configs = [], [], []
            # 如果是 application/json，则优先生效
            if request.content_type and 'application/json' in request.content_type:
                try:
                    body = json.loads(request.body.decode('utf-8') or '{}')
                    name = body.get('name', name)
                    description = body.get('description', description)
                    output_format = body.get('output_format', output_format)
                    field_configs = body.get('field_configs', field_configs or {})
                    processing_logic = body.get('processing_logic', processing_logic or {})
                    data_sources = body.get('data_sources', data_sources) or []
                    processing_rules = body.get('processing_rules', processing_rules) or []
                    output_configs = body.get('output_configs', output_configs) or []
                except Exception:
                    pass

            # 入库：模板 + 数据源 + 处理规则 + 输出配置，保证事务性
            with transaction.atomic():
                template = Template.objects.create(
                    name=name,
                    description=description,
                    created_by=request.user if request.user.is_authenticated else None,
                )

                # 数据源配置
                for idx, ds in enumerate(data_sources or []):
                    DataSourceConfig.objects.create(
                        template=template,
                        source_name=ds.get('source_name') or f'source_{idx + 1}',
                        source_type=ds.get('source_type', 'excel'),
                        read_direction=ds.get('read_direction', 'horizontal'),
                        source_order=ds.get('source_order', idx + 1),
                        data_range=ds.get('data_range', {}) or {},
                        header_config=ds.get('header_config', {}) or {},
                        join_keys=ds.get('join_keys', []) or [],
                        filter_conditions=ds.get('filter_conditions', []) or []
                    )

                # 处理规则
                for idx, rule in enumerate(processing_rules or []):
                    ProcessingRule.objects.create(
                        template=template,
                        rule_name=rule.get('rule_name') or f'rule_{idx + 1}',
                        rule_order=rule.get('rule_order', idx + 1),
                        rule_type=rule.get('rule_type', 'data_transformation'),
                        rule_config=rule.get('rule_config', {}) or {},
                        condition_config=rule.get('condition_config', {}) or {},
                        is_active=rule.get('is_active', True)
                    )

                # 输出配置：如果提供了 output_configs 列表则逐条创建；否则回退到 output_format 的默认配置
                if output_configs:
                    for idx, oc in enumerate(output_configs):
                        OutputConfig.objects.create(
                            template=template,
                            output_name=oc.get('output_name') or f'输出{idx + 1}',
                            output_type=oc.get('output_type', 'single_file'),
                            output_format=oc.get('output_format', 'excel'),
                            filename_template=oc.get('filename_template', '') or '',
                            output_config=oc.get('output_config', {}) or {}
                        )
                elif output_format:
                    OutputConfig.objects.create(
                        template=template,
                        output_name='默认输出',
                        output_type='single_file',
                        output_format=output_format,
                        output_config={}
                    )

            return JsonResponse({
                'success': True,
                'message': '模板创建成功',
                'template_id': str(template.id)
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e)
            })


def template_detail(request, template_id):
    """模板详情页面"""
    template = get_object_or_404(Template, id=template_id)
    # 从模板模型字段获取文件类型与输出格式（与用户创建返回保持一致：file_type=single_file，output_format=tabular）
    file_type = template.data_source_type
    output_format = template.template_type
    
    # 获取关联的配置数据
    data_sources = list(template.data_sources.all().values())
    processing_rules = list(template.processing_rules.all().values())
    output_configs = list(template.output_configs.all().values())
    
    return render(request, 'template_management/template_detail.html', {
        'template': template,
        'file_type': file_type,
        'output_format': output_format,
        'data_sources_json': json.dumps(data_sources, cls=DjangoJSONEncoder),
        'processing_rules_json': json.dumps(processing_rules, cls=DjangoJSONEncoder),
        'output_configs_json': json.dumps(output_configs, cls=DjangoJSONEncoder)
    })


def template_edit(request, template_id):
    """编辑模板"""
    template = get_object_or_404(Template, id=template_id)
    
    if request.method == 'GET':
        # 获取模板的完整配置
        template_data = {
            'id': str(template.id),  # 将UUID转换为字符串
            'name': template.name,
            'description': template.description,
            'file_type': (template.data_sources.first().source_type if hasattr(template, 'data_sources') and template.data_sources.exists() else 'excel'),
            'output_format': (template.output_configs.first().output_format if hasattr(template, 'output_configs') and template.output_configs.exists() else 'excel'),
            'field_configs': template.field_configs or {},
            'processing_logic': template.processing_logic or '{}',
            'processing_rules': [
                {
                    'id': str(rule.id),
                    'rule_name': rule.rule_name,
                    'rule_order': rule.rule_order,
                    'rule_type': rule.rule_type,
                    'rule_config': rule.rule_config,
                    'condition_config': rule.condition_config,
                    'is_active': rule.is_active,
                }
                for rule in template.processing_rules.all().order_by('rule_order') if hasattr(template, 'processing_rules')
            ],
        }
        
        # 新增：数据源与输出配置（用于前端保存时回传，避免被清空）
        data_sources = [
            {
                'id': str(ds.id),
                'source_name': ds.source_name,
                'source_type': ds.source_type,
                'read_direction': ds.read_direction,
                'source_order': ds.source_order,
                'data_range': ds.data_range,
                'header_config': ds.header_config,
                'join_keys': ds.join_keys,
                'filter_conditions': ds.filter_conditions,
            }
            for ds in template.data_sources.all().order_by('source_order') if hasattr(template, 'data_sources')
        ]
        output_configs = [
            {
                'id': str(oc.id),
                'output_name': oc.output_name,
                'output_type': oc.output_type,
                'output_format': oc.output_format,
                'filename_template': oc.filename_template,
                'output_config': oc.output_config,
            }
            for oc in template.output_configs.all() if hasattr(template, 'output_configs')
        ]
        template_data['data_sources'] = data_sources
        template_data['output_configs'] = output_configs
        
        return render(request, 'template_management/template_edit.html', {
            'template': template,
            'template_data': json.dumps(template_data, ensure_ascii=False),
            'field_configs_json': json.dumps(template.field_configs or {}, ensure_ascii=False),
            'processing_rules_json': json.dumps(template_data.get('processing_rules', []), ensure_ascii=False),
            'data_sources_json': json.dumps(data_sources, ensure_ascii=False),
            'output_configs_json': json.dumps(output_configs, ensure_ascii=False),
            'file_type': template_data.get('file_type'),
            'output_format': template_data.get('output_format')
        })
    
    elif request.method == 'POST':
        try:
            # 全量覆盖：解析基础字段
            name = request.POST.get('name', template.name)
            description = request.POST.get('description', template.description)
            output_format = request.POST.get('output_format', None)
            
            # 字段配置与处理逻辑
            field_configs = json.loads(request.POST.get('field_configs', '{}') or '{}')
            processing_logic_raw = request.POST.get('processing_logic', '{}') or '{}'
            try:
                processing_logic = json.loads(processing_logic_raw) if isinstance(processing_logic_raw, str) else (processing_logic_raw or {})
            except json.JSONDecodeError:
                processing_logic = {}
            
            # 关联块：默认空数组（全量覆盖语义）
            ds_raw = request.POST.get('data_sources', '[]') or '[]'
            pr_raw = request.POST.get('processing_rules', '[]') or '[]'
            oc_raw = request.POST.get('output_configs', '[]') or '[]'
            try:
                data_sources = json.loads(ds_raw) if isinstance(ds_raw, str) else (ds_raw or [])
                processing_rules = json.loads(pr_raw) if isinstance(pr_raw, str) else (pr_raw or [])
                output_configs = json.loads(oc_raw) if isinstance(oc_raw, str) else (oc_raw or [])
            except Exception:
                data_sources, processing_rules, output_configs = [], [], []
            
            # application/json 优先：缺省即视为空数组（全量覆盖）
            if request.content_type and 'application/json' in request.content_type:
                try:
                    body = json.loads(request.body.decode('utf-8') or '{}')
                    name = body.get('name', name)
                    description = body.get('description', description)
                    output_format = body.get('output_format', output_format)
                    field_configs = body.get('field_configs', field_configs or {})
                    processing_logic = body.get('processing_logic', processing_logic or {})
                    data_sources = body.get('data_sources', [])
                    processing_rules = body.get('processing_rules', [])
                    output_configs = body.get('output_configs', [])
                except Exception:
                    pass
            
            # 事务内全量覆盖
            with transaction.atomic():
                # 更新模板主表
                template.name = name
                template.description = description
                # 停止写入冗余JSON字段：field_configs 和 processing_logic
                # template.field_configs = field_configs
                # template.processing_logic = processing_logic
                template.save()
        
                # 删除并重建关联配置
                if hasattr(template, 'data_sources'):
                    template.data_sources.all().delete()
                if hasattr(template, 'processing_rules'):
                    template.processing_rules.all().delete()
                if hasattr(template, 'output_configs'):
                    template.output_configs.all().delete()
                
                # 重建数据源配置
                for idx, ds in enumerate(data_sources or []):
                    DataSourceConfig.objects.create(
                        template=template,
                        source_name=ds.get('source_name') or f'source_{idx + 1}',
                        source_type=ds.get('source_type', 'excel'),
                        read_direction=ds.get('read_direction', 'horizontal'),
                        source_order=ds.get('source_order', idx + 1),
                        data_range=ds.get('data_range', {}) or {},
                        header_config=ds.get('header_config', {}) or {},
                        join_keys=ds.get('join_keys', []) or [],
                        filter_conditions=ds.get('filter_conditions', []) or []
                    )
                
                # 重建处理规则
                for idx, rule in enumerate(processing_rules or []):
                    ProcessingRule.objects.create(
                        template=template,
                        rule_name=rule.get('rule_name') or f'rule_{idx + 1}',
                        rule_order=rule.get('rule_order', idx + 1),
                        rule_type=rule.get('rule_type', 'data_transformation'),
                        rule_config=rule.get('rule_config', {}) or {},
                        condition_config=rule.get('condition_config', {}) or {},
                        is_active=rule.get('is_active', True)
                    )
                
                # 重建输出配置
                if output_configs:
                    for idx, oc in enumerate(output_configs):
                        OutputConfig.objects.create(
                            template=template,
                            output_name=oc.get('output_name') or f'输出{idx + 1}',
                            output_type=oc.get('output_type', 'single_file'),
                            output_format=oc.get('output_format', 'excel'),
                            filename_template=oc.get('filename_template', '') or '',
                            output_config=oc.get('output_config', {}) or {}
                        )
                else:
                    # 未提供 output_configs 时：若提供 output_format，创建一条默认输出；否则保持无输出配置
                    if output_format:
                        OutputConfig.objects.create(
                            template=template,
                            output_name='默认输出',
                            output_type='single_file',
                            output_format=output_format,
                            output_config={}
                        )
            
            return JsonResponse({
                'success': True,
                'message': '模板更新成功'
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e)
            })





def template_preview(request, template_id):
    """模板预览"""
    template = get_object_or_404(Template, id=template_id)
    
    # 获取模板的详细配置信息
    template_info = {
        'basic_info': {
            'name': template.name,
            'description': template.description,
            'template_type': template.get_template_type_display() if hasattr(template, 'get_template_type_display') else template.template_type,
            'data_source_type': template.get_data_source_type_display() if hasattr(template, 'get_data_source_type_display') else template.data_source_type,
            'created_at': template.created_at.strftime('%Y-%m-%d %H:%M:%S'),
            'updated_at': template.updated_at.strftime('%Y-%m-%d %H:%M:%S')
        },
        'data_sources': [
            {
                'source_name': ds.source_name,
                'source_type': ds.get_source_type_display() if hasattr(ds, 'get_source_type_display') else ds.source_type,
                'read_direction': ds.get_read_direction_display() if hasattr(ds, 'get_read_direction_display') else ds.read_direction,
                'data_range': ds.data_range,
                'header_config': ds.header_config,
                'join_keys': ds.join_keys,
                'filter_conditions': ds.filter_conditions
            }
            for ds in template.data_sources.all().order_by('source_order') if hasattr(template, 'data_sources')
        ],
        'processing_rules': [
            {
                'rule_name': rule.rule_name,
                'rule_type': rule.get_rule_type_display() if hasattr(rule, 'get_rule_type_display') else rule.rule_type,
                'rule_config': rule.rule_config,
                'condition_config': rule.condition_config,
                'is_active': rule.is_active
            }
            for rule in template.processing_rules.all().order_by('rule_order') if hasattr(template, 'processing_rules')
        ],
        'output_configs': [
            {
                'output_name': output.output_name,
                'output_type': output.get_output_type_display() if hasattr(output, 'get_output_type_display') else output.output_type,
                'output_format': output.get_output_format_display() if hasattr(output, 'get_output_format_display') else output.output_format,
                'output_config': output.output_config,
                'filename_template': output.filename_template
            }
            for output in template.output_configs.all() if hasattr(template, 'output_configs')
        ]
    }
    
    return render(request, 'template_management/template_preview.html', {
        'template': template,
        'template_info': template_info
    })


def template_test(request, template_id):
    """模板测试"""
    template = get_object_or_404(Template, id=template_id)
    
    if request.method == 'GET':
        # 获取模板需要的数据源信息
        data_sources_info = [
            {
                'source_name': ds.source_name,
                'source_type': ds.source_type,
                'description': f"{ds.get_source_type_display() if hasattr(ds, 'get_source_type_display') else ds.source_type} - {ds.get_read_direction_display() if hasattr(ds, 'get_read_direction_display') else ds.read_direction}"
            }
            for ds in template.data_sources.all().order_by('source_order') if hasattr(template, 'data_sources')
        ]
        
        return render(request, 'template_management/template_test.html', {
            'template': template,
            'data_sources_info': data_sources_info
        })
    
    elif request.method == 'POST':
        try:
            # 获取上传的文件
            uploaded_files = {}
            if hasattr(template, 'data_sources'):
                for ds in template.data_sources.all():
                    file_key = f"file_{ds.source_name}"
                    if file_key in request.FILES:
                        uploaded_files[ds.source_name] = request.FILES[file_key]
            
            if not uploaded_files:
                return JsonResponse({
                    'success': False,
                    'error': '请上传至少一个数据文件'
                })
            
            # 简单处理上传的文件
            result = {
                'success': True,
                'message': f'成功上传 {len(uploaded_files)} 个文件'
            }
            
            return JsonResponse(result)
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e)
            })


@csrf_exempt
@require_http_methods(["POST"])
def template_process_data(request):
    """使用模板处理数据"""
    try:
        template_id = request.POST.get('template_id')
        if not template_id:
            return JsonResponse({
                'success': False,
                'error': '请选择模板'
            })
        
        template = get_object_or_404(Template, id=template_id)
        
        # 获取上传的文件
        if 'data_file' not in request.FILES:
            return JsonResponse({
                'success': False,
                'error': '请上传数据文件'
            })
        
        uploaded_file = request.FILES['data_file']
        
        # 读取文件数据（根据扩展名自动判断）
        try:
            filename_lower = uploaded_file.name.lower()
            if filename_lower.endswith(('.xlsx', '.xls')):
                # 读取Excel文件
                data = pd.read_excel(uploaded_file, sheet_name=None)  # 读取所有工作表
            elif filename_lower.endswith('.csv'):
                # 读取CSV文件
                data = pd.read_csv(uploaded_file)
            else:
                return JsonResponse({
                    'success': False,
                    'error': f'不支持的文件类型: {uploaded_file.name}'
                })
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': f'文件读取失败: {str(e)}'
            })
        
        # 简单的数据处理逻辑
        result = {
            'success': True,
            'data': data,
            'message': f'成功读取文件: {uploaded_file.name}'
        }
        
        if result['success']:
            # 记录使用日志
            TemplateUsageLog.objects.create(
                template=template,
                input_file_name=uploaded_file.name,
                input_file_size=uploaded_file.size,
                processing_status='success',
                processing_result=result.get('message', ''),
                output_records_count=len(result['data']) if isinstance(result['data'], pd.DataFrame) else sum(len(df) for df in result['data'].values()) if isinstance(result['data'], dict) else 0
            )
        else:
            # 记录错误日志
            TemplateUsageLog.objects.create(
                template=template,
                input_file_name=uploaded_file.name,
                input_file_size=uploaded_file.size,
                processing_status='error',
                error_message=result.get('error', ''),
                processing_result=result.get('message', '')
            )
        
        return JsonResponse(result)
        
    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': str(e)
        })


def template_delete(request, template_id):
    """删除模板"""
    if request.method == 'DELETE':
        try:
            template = get_object_or_404(Template, id=template_id)
            template.is_active = False
            template.save()
            
            return JsonResponse({
                'success': True,
                'message': '模板删除成功'
            })
            
        except Exception as e:
            return JsonResponse({
                'success': False,
                'error': str(e)
            })
    
    return JsonResponse({
        'success': False,
        'error': '不支持的请求方法'
    })


def get_template_list(request):
    """获取模板列表API"""
    templates = Template.objects.filter(is_active=True).order_by('-created_at')
    
    template_list = [
        {
            'id': str(template.id),
            'name': template.name,
            'description': template.description,
            'file_type': (template.data_sources.first().source_type if hasattr(template, 'data_sources') and template.data_sources.exists() else 'excel'),
            'output_format': (template.output_configs.first().output_format if hasattr(template, 'output_configs') and template.output_configs.exists() else 'excel'),
            'created_at': template.created_at.strftime('%Y-%m-%d %H:%M:%S'),
            'usage_count': template.usage_logs.count() if hasattr(template, 'usage_logs') else 0
        }
        for template in templates
    ]
    
    return JsonResponse({
        'success': True,
        'templates': template_list
    })


class TemplateAPIView(APIView):
    """模板管理API"""
    parser_classes = (MultiPartParser, FormParser)
    permission_classes = [IsAuthenticated]
    
    def get(self, request, template_id=None):
        """获取模板详情"""
        if template_id:
            try:
                template = Template.objects.get(id=template_id)
                serializer = TemplateSerializer(template)
                return Response(serializer.data, status=status.HTTP_200_OK)
            except Template.DoesNotExist:
                return Response({
                    'error': '模板不存在'
                }, status=status.HTTP_404_NOT_FOUND)
        else:
            return template_list(request)
    
    def post(self, request):
        """创建新模板"""
        try:
            serializer = TemplateSerializer(data=request.data)
            if serializer.is_valid():
                template = serializer.save(created_by=request.user)
                return Response({
                    'message': '模板创建成功',
                    'template': TemplateSerializer(template).data
                }, status=status.HTTP_201_CREATED)
            else:
                return Response({
                    'error': '数据验证失败',
                    'details': serializer.errors
                }, status=status.HTTP_400_BAD_REQUEST)
                
        except Exception as e:
            return Response({
                'error': f'创建模板失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def put(self, request, template_id):
        """更新模板"""
        try:
            template = Template.objects.get(id=template_id)
            serializer = TemplateSerializer(template, data=request.data, partial=True)
            if serializer.is_valid():
                template = serializer.save()
                return Response({
                    'message': '模板更新成功',
                    'template': TemplateSerializer(template).data
                }, status=status.HTTP_200_OK)
            else:
                return Response({
                    'error': '数据验证失败',
                    'details': serializer.errors
                }, status=status.HTTP_400_BAD_REQUEST)
                
        except Template.DoesNotExist:
            return Response({
                'error': '模板不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'error': f'更新字段配置失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def delete(self, request, template_id):
        """删除模板"""
        try:
            template = Template.objects.get(id=template_id)
            template.delete()
            return Response({
                'success': True,
                'message': '模板删除成功'
            }, status=status.HTTP_200_OK)
        except Template.DoesNotExist:
            return Response({
                'success': False,
                'error': '模板不存在'
            }, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({
                'success': False,
                'error': f'删除模板失败: {str(e)}'
            }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)




@api_view(['POST'])
@permission_classes([IsAuthenticated])
def upload_excel_template(request):
    """上传Excel模板文件并解析结构"""
    if 'file' not in request.FILES:
        return Response({'error': '请选择文件'}, status=status.HTTP_400_BAD_REQUEST)
    
    uploaded_file = request.FILES['file']
    
    # 验证文件类型
    if not uploaded_file.name.lower().endswith(('.xlsx', '.xls')):
        return Response({'error': '只支持Excel文件(.xlsx, .xls)'}, status=status.HTTP_400_BAD_REQUEST)
    
    try:
        # 使用Excel处理器解析文件
        processor = ExcelProcessor(uploaded_file)
        
        if not processor.load_excel():
            return Response({'error': '无法加载Excel文件'}, status=status.HTTP_400_BAD_REQUEST)
        
        # 提取文件结构
        structure = processor.extract_structure()
        
        # 关闭处理器
        processor.close()
        
        return Response({
            'success': True,
            'structure': structure,
            'message': 'Excel文件解析成功'
        })
        
    except Exception as e:
        return Response(
            {'error': f'解析Excel文件失败: {str(e)}'}, 
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def create_visual_template(request):
    """创建可视化配置模板"""
    try:
        data = request.data
        
        # 创建模板
        template = Template.objects.create(
            name=data.get('name'),
            description=data.get('description', ''),
            template_type='visual_config',
            excel_structure=data.get('excel_structure', {}),
            field_configs=data.get('field_configs', {}),
            created_by=request.user
        )
        
        # 保存上传的Excel文件
        if 'template_file' in request.FILES:
            template.template_file = request.FILES['template_file']
            template.save()
        
        # 创建详细的字段配置记录
        field_configs = data.get('field_configs', {})
        for field_name, config in field_configs.items():
            FieldConfig.objects.create(
                template=template,
                field_name=field_name,
                cell_position=config.get('cell_position', ''),
                rule_type=config.get('rule_type', 'assign'),
                split_delimiter=config.get('split_delimiter', ''),
                split_type=config.get('split_type', ''),
                split_index=config.get('split_index'),
                split_regex=config.get('split_regex', ''),
                aggregate_direction=config.get('aggregate_direction', ''),
                aggregate_count=config.get('aggregate_count'),
                aggregate_delimiter=config.get('aggregate_delimiter', ','),
                generate_pattern=config.get('generate_pattern', ''),
                generate_field_name=config.get('generate_field_name', ''),
                assign_mode=config.get('assign_mode', 'overwrite'),
                assign_value=config.get('assign_value', ''),
                is_active=config.get('is_active', True),
                order=config.get('order', 0),
                created_by=request.user
            )
        
        serializer = TemplateSerializer(template)
        return Response({
            'success': True,
            'template': serializer.data,
            'message': '可视化模板创建成功'
        }, status=status.HTTP_201_CREATED)
        
    except Exception as e:
        return Response(
            {'error': f'创建模板失败: {str(e)}'}, 
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )





@api_view(['POST'])
@permission_classes([IsAuthenticated])
def test_output(request):
    """测试输出API"""
    try:
        print("test_output")
        # 获取上传的文件
        if 'file' not in request.FILES:
            return Response(
                {'error': '请上传测试文件'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        test_file = request.FILES['file']
        field_configs = request.data.get('fieldConfigs', '{}')
        print(request.data)
        # 解析字段配置
        try:
            # 处理不同格式的field_configs
            if isinstance(field_configs, list) and len(field_configs) > 0:
                # 如果是列表（FormData传输时的格式），取第一个元素并解析
                config_str = field_configs[0]
                raw_configs = json.loads(config_str) if isinstance(config_str, str) else config_str
            elif isinstance(field_configs, str):
                # 如果是字符串，直接解析
                raw_configs = json.loads(field_configs)
            else:
                # 如果已经是对象，直接使用
                raw_configs = field_configs
            
            # 处理fieldConfigs的数据结构
            # fieldConfigs可能是 {fieldName: [rules]} 或 {fieldName: config} 的格式
            configs = {}
            for field_name, field_data in raw_configs.items():
                if isinstance(field_data, list) and len(field_data) > 0:
                    # 如果是规则数组，使用所有规则
                    configs[field_name] = field_data
                elif isinstance(field_data, dict):
                    # 如果是单个配置对象，转换为数组格式
                    configs[field_name] = [field_data]
        except json.JSONDecodeError:
            return Response(
                {'error': '字段配置格式错误'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 读取测试文件
        import pandas as pd
        import io
        
        # 读取Excel文件
        file_content = test_file.read()
        df = pd.read_excel(io.BytesIO(file_content))
        
        # 应用字段配置进行数据处理
        processed_data = []
        for index, row in df.iterrows():
            processed_row = {}
            for field_name, rule_list in configs.items():
                # 处理该字段的所有规则
                field_values = []
                for config in rule_list:
                    if config.get('is_active', True):
                        # 根据规则类型处理数据
                        rule_type = config.get('rule_type', 'direct')
                        source_field = config.get('source_field', field_name)
                        
                        if source_field in row:
                            value = row[source_field]
                            
                            if rule_type == 'split':
                                # 分割处理
                                split_index = config.get('split_index', 0)
                                split_regex = config.get('split_regex', ',')
                                if pd.notna(value):
                                    parts = str(value).split(split_regex)
                                    if split_index < len(parts):
                                        field_values.append(parts[split_index].strip())
                                    else:
                                        field_values.append('')
                                else:
                                    field_values.append('')
                            
                            elif rule_type == 'assign':
                                # 赋值处理
                                field_values.append(config.get('assign_value', ''))
                            
                            elif rule_type == 'generate':
                                # 生成处理
                                generate_mode = config.get('generate_mode', 'pattern')
                                if generate_mode == 'pattern':
                                    pattern = config.get('generate_pattern', '')
                                    field_values.append(pattern.replace('{value}', str(value) if pd.notna(value) else ''))
                                else:
                                    field_values.append(str(value) if pd.notna(value) else '')
                            
                            else:
                                # 直接映射
                                field_values.append(str(value) if pd.notna(value) else '')
                        else:
                            field_values.append('')
                
                # 将所有规则的结果合并（用逗号分隔，或取最后一个非空值）
                if field_values:
                    # 过滤空值，如果有非空值则用逗号连接，否则为空
                    non_empty_values = [v for v in field_values if v]
                    processed_row[field_name] = ', '.join(non_empty_values) if non_empty_values else ''
                else:
                    processed_row[field_name] = ''
            
            processed_data.append(processed_row)
        
        # 限制返回的数据量（前10行用于预览）
        preview_data = processed_data[:10]
        
        return Response({
            'success': True,
            'data': preview_data,
            'total_rows': len(processed_data),
            'preview_rows': len(preview_data),
            'columns': list(configs.keys()) if configs else []
        })
        
    except Exception as e:
        import traceback
        error_msg = f'测试输出失败: {str(e)}'
        print(f"Error in test_output: {error_msg}")
        print(f"Traceback: {traceback.format_exc()}")
        return Response(
            {'error': error_msg}, 
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )


from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated

@api_view(['PUT'])
@permission_classes([IsAuthenticated])
def update_processing_rules(request, template_id):
    """更新指定模板的处理规则集合（幂等：根据传入列表进行新增/更新/删除）"""
    try:
        template = Template.objects.get(id=template_id)
    except Template.DoesNotExist:
        return Response({'error': '模板不存在'}, status=status.HTTP_404_NOT_FOUND)

    payload = request.data.get('processing_rules')
    # 兼容 application/json 直接传数组
    if payload is None and isinstance(request.data, list):
        payload = request.data

    if isinstance(payload, str):
        try:
            rules_data = json.loads(payload)
        except Exception as e:
            return Response({'error': f'processing_rules 解析失败: {str(e)}'}, status=status.HTTP_400_BAD_REQUEST)
    else:
        rules_data = payload or []

    # 收集现有规则，便于差异化更新
    existing_rules = {str(r.id): r for r in ProcessingRule.objects.filter(template=template)}
    incoming_ids = set()

    # 更新或创建
    for item in rules_data:
        rid = str(item.get('id')) if item.get('id') else None
        data = {
            'rule_name': item.get('rule_name', ''),
            'rule_order': item.get('rule_order', 0),
            'rule_type': item.get('rule_type', ''),
            'rule_config': item.get('rule_config', {}) or {},
            'condition_config': item.get('condition_config', {}) or {},
            'is_active': bool(item.get('is_active', True)),
        }
        if rid and rid in existing_rules:
            # 更新
            rule = existing_rules[rid]
            for k, v in data.items():
                setattr(rule, k, v)
            rule.save()
            incoming_ids.add(rid)
        else:
            # 新建
            rule = ProcessingRule.objects.create(template=template, created_by=request.user, **data)
            incoming_ids.add(str(rule.id))

    # 删除未在传入列表中的规则
    for rid, rule in existing_rules.items():
        if rid not in incoming_ids:
            rule.delete()

    # 返回最新规则
    updated = ProcessingRule.objects.filter(template=template).order_by('rule_order')
    serializer = ProcessingRuleSerializer(updated, many=True)
    return Response({'success': True, 'processing_rules': serializer.data}, status=status.HTTP_200_OK)